using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using GameOnCopyBook.Menu;
using GameOnCopyBook.Time;

using InputManagement;
//using GameOnCopyBook.Input;



namespace GameOnCopyBook.Logic
{
    /// <summary>
    /// Questo è un componente del gioco che implementa IUpdateable.
    /// </summary>
    public class Logic : Microsoft.Xna.Framework.DrawableGameComponent
    {
        
        public Logic(Game game)
            : base(game)
        {
            
        }

        /// <summary>
        /// Consente al componente del gioco di eseguire l'inizializzazione necessaria prima dell'inizio
        /// dell'esecuzione. Qui è possibile eseguire query per eventuali servizi necessari e caricare contenuto.
        /// </summary>
        public override void Initialize()
        {
                       
            // TODO: aggiungere qui il codice di inizializzazione
            IInputService inputService = Game.Services.GetService(typeof(IInputService)) as IInputService;

            inputService.OnShoot += GameLogic.Shoot;
            inputService.OnSuperShoot += GameLogic.SuperShot;
          
          
            Menu.Menu.soundMgr.LoadContent(Game.Content);
            Menu.Menu.soundMgr.PlayInGame();
            base.Initialize();
        }

        protected override void Dispose(bool disposing)
        {
            Game.Services.RemoveService(typeof(IInputService));    
            base.Dispose(disposing);
        }

        static public void SaveState()
        {
            FileStream stream = File.Open("GameState.sav", FileMode.OpenOrCreate, FileAccess.Write);
            try
            {
                var binary_formatter = new BinaryFormatter();
                binary_formatter.Serialize(stream, GameLogic.game_state);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.Message);
            }
            finally
            {
                stream.Close();
            }
            
        }

        static public void LoadState()
        {
            FileStream stream = File.Open("GameState.sav", FileMode.OpenOrCreate, FileAccess.Read);

            try
            {
                var binary_formatter = new BinaryFormatter();
                GameLogic.game_state = (GameState.GameState)binary_formatter.Deserialize(stream);
                
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.Message);
            }
            finally
            {
                stream.Close();
            }
            
            
           
        }

        /// <summary>
        /// Consente al componente del gioco di aggiornare se stesso.
        /// </summary>
        /// <param name="gameTime">Fornisce uno snapshot dei valori di temporizzazione.</param>
        public override void Update(GameTime gameTime)
        {
            var dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
                        
            
            if (GameLogic.game_state.Player.Alive)
            {
                              
                GameLogic.updateState(dt);
                GameLogic.update_script();

                Casanova.commit_variable_updates();

                Menu.Menu.soundMgr.Update();
            }
            else
            {
                MediaPlayer.Stop();
                while (Game.Components.Count > 0)
                {
                    ((GameComponent)Game.Components[0]).Dispose();
                }

                Game.Components.Clear();

                
                Game.Components.Add(new Rendering.Rendering(Game));
                Game.Components.Add(new InputManager(Game)); 
                Game.Components.Add(new Menu.GameOver(Game));
                
            }
            
            if (InputManager.GetState().save)
            {
                SaveState();
            }
            
            if (InputManager.GetState().pause)
            {
                SaveState();
                MediaPlayer.Pause();
                while (Game.Components.Count > 0)
                {
                    ((GameComponent)Game.Components[0]).Dispose();
                }

                Game.Components.Clear();


                Game.Components.Add(new Rendering.Rendering(Game));
                Game.Components.Add(new InputManager(Game));                
                Game.Components.Add(new Pause(Game));
               
            }
            
            base.Update(gameTime);
        }

        
    }
}
